package com.yoyosys.common.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * VO/DTO/BO/Entity/DO等关联实体转换工具
 */
@Slf4j
public class ObjUtil {
    /**
     * 对象转成Map
     * @param object
     * @return
     */
    public static Map<String, Object> objToMap(Object object){
        String jsonStr = JSONObject.toJSONString(object);
        Map<String,Object> map = JSONObject.parseObject(jsonStr, new TypeReference<Map<String, Object>>(){});
        return  map;
    }

    public static JSONObject strToJson(Object obj){
        if(obj == null){
            return new JSONObject();
        }
        if(obj instanceof JSONObject){
            return (JSONObject)obj;
        }

        String str = obj.toString();
        if(CommonUtil.isBlank(str)){
            return new JSONObject();
        }
        try{
            JSONObject json = JSON.parseObject(str.trim());
            if(json == null){
                return new JSONObject();
            } else {
                return json;
            }
        }catch(Exception e){
            return new JSONObject();
        }
    }
    public static JSONArray strToJsonArray(Object obj){
        if(obj == null){
            return new JSONArray();
        }
        if(obj instanceof JSONArray){
            return (JSONArray)obj;
        }

        try{
            JSONArray json = JSON.parseArray(obj.toString());
            if(json == null){
                return new JSONArray();
            } else {
                return json;
            }
        }catch(Exception e){
            return new JSONArray();
        }
    }


    /**
     * 功能描述：把java对象转换成JSON数据
     * @param object java对象
     * @return JSON数据
     */
    public static String objToJson(Object object) {
        return JSON.toJSONString(object, SerializerFeature.WriteMapNullValue);
    }

    /**
     * 功能描述：把JSON数据转换成指定的java对象
     * @param jsonData JSON数据
     * @param clazz 指定的java对象
     * @return 指定的java对象
     */
    public static <T> T jsonToObj(String jsonData, Class<T> clazz) {
        return JSON.parseObject(jsonData, clazz);
    }

    /**
     * 功能描述：把JSON数据转换成指定的java对象列表
     * @param jsonData JSON数据
     * @param clazz 指定的java对象
     * @return List<T>
     */
    public static <T> List<T> jsonToList(String jsonData, Class<T> clazz) {
        return JSON.parseArray(jsonData, clazz);
    }

    /**
     * 功能描述：把JSON数据转换成较为复杂的List<Map<String, Object>>
     * @param jsonData JSON数据
     * @return List<Map<String, Object>>
     */
    public static List<Map<String, Object>> jsonToListMap(String jsonData) {
        return JSON.parseObject(jsonData, new TypeReference<List<Map<String, Object>>>() {});
    }

    /**
     * 功能描述：把JSONArray数据转换成较为复杂的List<Map<String, Object>>
     * @param jsonArray JSONArray数据
     * @return List<Map<String, Object>>
     */
    public static List<Map<String, Object>> jsonArrayToList(JSONArray jsonArray) {
        return JSON.parseObject(JSON.toJSONString(jsonArray), new TypeReference<List<Map<String, Object>>>() {});
    }


    /**
     * 同一类Java DTO 对象之间转换。使用反射机制，比较JSON格式化反格式化高效。支持常见属性类型的转换
     * @param source 源dto对象
     * @param clazz 目标java对象
     * @return 指定的java对象
     */
    public static <T> T to(Object source, Class<T> clazz){
        return to(source, clazz, null);
    }

    /**
     * 同一类Java DTO 对象之间转换。使用反射机制，比较JSON格式化反格式化高效。支持常见属性类型的转换
     * @param source 源dto对象
     * @param clazz 目标java对象
     * @param ignoreProperties 要忽略的属性名,多个用英文逗号分割
     * @return 指定的java对象
     */
    public static <T> T to(Object source, Class<T> clazz, String ignoreProperties){
        if(source == null){
            return null;
        }

        T target = (T) BeanUtils.instantiateClass(clazz);
        List<String> ignoreList = null;
        if(CommonUtil.isNotBlank(ignoreProperties)){
            ignoreList = Arrays.asList(ignoreProperties.split(","));
        }

        List<Field> targetFields = ReflectionUtils.getDeclaredFields(clazz);//获取所有字段，包括继承的
        for (Field targetField : targetFields) {
            String fieldName = targetField.getName();

            if(ignoreList != null  && ignoreList.contains(fieldName)){
                continue;
            }

            //继承自Serializable接口的字段
            if("serialVersionUID".equals(fieldName)){
                continue;
            }

            //处理字段值
            //------------------------------------
            Object value = ReflectionUtils.getFieldValue(source, fieldName);
            if(value == null){
                ReflectionUtils.setFieldValue(target, targetField, null);
                continue;
            }

            String fieldClass = targetField.getType().getSimpleName();
            if(CommonUtil.isBlank(fieldClass)){
                continue;
            }
            if("Timestamp".equals(fieldClass) || "Date".equals(fieldClass)){//处理日期类型
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toDate(value));
            } else if("String".equals(fieldClass)){
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toString(value));
            } else if("Boolean".equals(fieldClass)){
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toBoolean(value));
            } else if("Integer".equals(fieldClass)){
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toInteger(value));
            } else if("Float".equals(fieldClass)){
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toFloat(value));
            } else if("Long".equals(fieldClass)){
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toLong(value));
            } else if("Double".equals(fieldClass)){
                ReflectionUtils.setFieldValue(target, targetField, CommonUtil.toDouble(value));
            } else if("BigInteger".equals(fieldClass)){//将java.math.BigInteger类型转换简单类型
                ReflectionUtils.setFieldValue(target, targetField, new BigInteger(CommonUtil.toString(value)));
            } else if("BigDecimal".equals(fieldClass)){//将java.math.BigDecimal类型转换简单类型
                ReflectionUtils.setFieldValue(target, targetField, new BigDecimal(CommonUtil.toString(value)));
            } else {
                ReflectionUtils.setFieldValue(target, targetField, value);
            }
        }//for

        return target;
    }

    /**
     * 同一类Java DTO 对象列表之间转换
     * @param list dto对象列表
     * @param clazz 返回list中的目标元素java类
     * @return List<T>
     */
    public static <T> List<T> toList(List<?> list, Class<T> clazz) {
        List<T> result = new ArrayList<>();
        if(list == null || list.isEmpty()){
            return result;
        }
        list.forEach(e -> {
            result.add(to(e, clazz));
        });

        return result;
    }
    /**
     * 同一类Java DTO 对象列表之间转换
     * @param list dto对象列表
     * @param clazz 返回list中的目标元素java类
     * @param ignoreProperties 要忽略的属性名,多个用英文逗号分割
     * @return List<T>
     */
    public static <T> List<T> toList(List<?> list, Class<T> clazz, String ignoreProperties) {
        List<T> result = new ArrayList<>();
        if(list == null || list.isEmpty()){
            return result;
        }
        list.forEach(e -> {
            result.add(to(e, clazz, ignoreProperties));
        });

        return result;
    }

}
